package com.fzebu.fastboot.uuid;

import lombok.Builder;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;
import weaver.conn.RecordSet;

import java.util.ArrayList;
import java.util.List;

/**
 * @author Jack
 * @version 1.0.0
 * @create 2020/2/23 17:07
 */
@Builder
public class SeqCode {

    private static final String PREFIX = "$$CUSTOM_SEQ_";

    private static final String SEQ_INDEX_PROC = "CUSTOM_NEXT_SEQ";

    private static final char SEPARATOR = '-';

    private final String seqTag;

    private final String seqName;

    private final String codeTable;

    private final String codeField;

    private final int startCode;

    private final int digits;

    private final int increment;

    public long getNextId() {
        RecordSet rs = new RecordSet();
        return this.executeProc(rs);
    }

    private synchronized long executeProc(RecordSet rs) {
        List<String> params = new ArrayList<>();
        params.add(this.seqTag);
        params.add(this.seqName);
        params.add(String.valueOf(this.startCode));
        params.add(String.valueOf(this.increment));
        rs.executeProc(SEQ_INDEX_PROC, params);
        if (rs.next()) {
            return NumberUtils.toLong(rs.getString(1));
        }
        return -1L;
    }

    public String getNextSeqCode() {
        long nextId = this.getNextId();
        return this.seqName + SEPARATOR + String.format("%0" + this.digits + "d", nextId);
    }

    public static class SeqCodeBuilder {

        private SeqCodeBuilder() {
            this.digits = 3;
            this.increment = 1;
        }

        public SeqCode build() {
            if (StringUtils.isEmpty(this.seqName)) {
                throw new IllegalArgumentException("sequence name is null");
            }
            if (StringUtils.isEmpty(this.codeTable)) {
                throw new IllegalArgumentException("code table is null");
            }
            if (StringUtils.isEmpty(this.codeField)) {
                throw new IllegalArgumentException("code field is null");
            }
            if (StringUtils.isEmpty(this.seqTag)) {
                this.seqTag = PREFIX + this.codeTable + SEPARATOR + this.codeField + SEPARATOR + this.seqName;
            }
            return new SeqCode(this.seqTag, this.seqName, this.codeTable, this.codeField, this.startCode, this.digits, this.increment);
        }
    }
}
